#include "WorkTask.h"
using namespace yazi::task;

#include "SocketHandler.h"
using namespace yazi::socket;

#include "Singleton.h"
#include "Logger.h"
using namespace yazi::utility;

#include "WorkFlow.h"
using namespace yazi::engine;

#include <cstring>
#include <cerrno>
#include <sstream>


WorkTask::WorkTask(Socket *socket) : Task((void *)socket)
{
}

WorkTask::~WorkTask()
{
}

void WorkTask::run()
{
    SocketHandler *sockethandler = Singleton<SocketHandler>::instance();
    Socket *socket = static_cast<Socket *>(m_data);
    struct MsgHead msghead;
    memset(&msghead, 0, sizeof msghead);
    int len = socket->recv((char*)&msghead, sizeof msghead);
    if (len == 0)
    {
        error("socket closed by peer");
        sockethandler->remove(socket);
        return;
    }
    if (len == -1 && errno == EAGAIN)
    {
        error("socket recv len: %d, error msg: EAGAIN, errno: %d", len, errno);
        sockethandler->attach(socket);
        return;
    }
    if (len == -1 && errno == EWOULDBLOCK)
    {
        error("socket recv len: %d, error msg: EWOULDBLOCK, errno: %d", len, errno);
        sockethandler->attach(socket);
        return;
    }
    if (len == -1 && errno == EINTR)
    {
        error("socket recv len: %d, error msg: EINTR, errno: %d", len, errno);
        sockethandler->attach(socket);
        return;
    }
    if (len != sizeof(msghead))
    {
        error("recv msg error, received len: %d, errno: %d", len, errno);
        sockethandler->remove(socket);
        return;
    }
    info("recv MsgHead: flag: %s, cmd: %d, len: %d", msghead.flag, msghead.cmd, msghead.len);

    if (strncmp(msghead.flag, "work", 4) != 0)
    {
        error("recv msg error, received flag: %s", msghead.flag);
        sockethandler->remove(socket);
        return;
    }
    if (msghead.len >= (uint32_t)recv_buf_len)
    {
        error("recv msg error, received len: %d, larger than recv_buf_len", msghead.len);
        sockethandler->remove(socket);
        return;
    }
    char buf[recv_buf_len];
    memset(buf, 0, sizeof buf);
    len = socket->recv(buf, msghead.len);
    if (len == -1 && errno == EAGAIN)
    {
        error("socket recv len: %d, error msg: EAGAIN, errno: %d", len, errno);
        sockethandler->remove(socket);
        return;
    }
    if (len == -1 && errno == EWOULDBLOCK)
    {
        error("socket recv len: %d, error msg: EWOULDBLOCK, errno: %d", len, errno);
        sockethandler->remove(socket);
        return;
    }
    if (len == -1 && errno == EINTR)
    {
        error("socket recv len: %d, error msg: EINTR, errno: %d", len, errno);
        sockethandler->remove(socket);
        return;
    }
    if (len != (int)msghead.len)
    {
        error("recv msg body error, received len: %d, errno: %d", len, errno);
        sockethandler->remove(socket);
        return;
    }
    info("recv msg body len: %d, msg data: %s", len, buf);

    // WorkFlow 相关工作
    WorkFlow* workflow = Singleton<WorkFlow>::instance();
    ostringstream os;
    os << (int)msghead.cmd;
    string work = os.str();
    string input = buf;
    string output;
    workflow->run(work, input, output);
    socket->send(output.c_str(), output.length());
    sockethandler->attach(socket);
}

void WorkTask::destroy()
{
    debug("work job destroy");
    delete this;
}
